package hcs.model;

import hcs.interfaces.RoomManagementStrategy;
import hcs.model.Room.WindowState;

/**
 * Implements the presence strategy
 */
public class PresenceManagementStrategy extends RoomManagementStrategy {

	/**
	 * Instantiate a presence strategy for the requested room
	 * @param room the room to be controlled.
	 */
	public PresenceManagementStrategy(Room room) {
		super(room);
	}

	public void applyStrategy(boolean windowManual) {
		Environment env = room.getHouseController().getEnvironment();
		double stdPresTemp = room.getSettings().getStandardPresenceTemp();

		WindowState desiredWS; // desired window state (the next state of the window)

		/* Temperature following */

		if (room.getTemperature() < stdPresTemp-1) {
			// the room is cooler than the requested temperature, try to warm it

			// put the heater at maximum temperature
			room.setHeaterTarget(70);

			// check if it is suitable to open the window
			if (env.getTemperature() > room.getTemperature()) {
				// outside is warmer than inside, and we must warm inside, let's open the window
				desiredWS = WindowState.OPEN;
			} else {
				// outside is cooler than inside, close the window
				desiredWS = WindowState.CLOSED;
			}
		} else {
			if (room.getTemperature() >= stdPresTemp-1 && room.getTemperature() <= stdPresTemp+1) {
				// the room is at the right temperature, try to keep it
				room.setHeaterTarget(stdPresTemp);
				
				// we want the window closed
				desiredWS = WindowState.CLOSED;

			} else {
				// the room is warmer than requested. Shut down the heater, not to waste energy
				room.setHeaterTarget(0);
				// and, if outside is cooler than inside, tilt the window to cool the room down
				if (env.getTemperature() < room.getTemperature()) {
					desiredWS = WindowState.TILTED;
				} else {
					// outside temperature does not help in cooling the room down, let's close the window
					desiredWS = WindowState.CLOSED;
				}
			}
		}
		
		/* Real window actuation */
		
		// if desired window state is open, but it's raining, our desired window state becomes tilted
		if (env.isRaining() && desiredWS.equals(WindowState.OPEN)) {
			desiredWS = WindowState.TILTED;
		}
		
		// only change the window position if the window is not in manual handling
		if (!windowManual) {
			room.setWindowStatus(desiredWS);
		}
	}

	@Override
	protected double getTemperatureToFollow() {
		return room.getSettings().getStandardPresenceTemp();
	}

	@Override
	protected WindowState roomIsOK() {
		// the room is at the right temperature, try to keep it
		room.setHeaterTarget(getTemperatureToFollow());
		
		// we want the window closed
		return WindowState.CLOSED;
	}

	@Override
	protected WindowState roomIsTooCool() {
		// the room is cooler than the requested temperature, try to warm it
		Environment env = room.getHouseController().getEnvironment();
		WindowState desiredWS;
		// put the heater at maximum temperature
		room.setHeaterTarget(70);

		// check if it is suitable to open the window
		if (env.getTemperature() > room.getTemperature()) {
			// outside is warmer than inside, and we must warm inside, let's open the window
			desiredWS = WindowState.OPEN;
		} else {
			// outside is cooler than inside, close the window
			desiredWS = WindowState.CLOSED;
		}
		return desiredWS;
	}

	@Override
	protected WindowState roomIsTooWarm() {
		Environment env = room.getHouseController().getEnvironment();
		WindowState desiredWS;
		// the room is warmer than requested. Shut down the heater, not to waste energy
		room.setHeaterTarget(0);
		// and, if outside is cooler than inside, tilt the window to cool the room down
		if (env.getTemperature() < room.getTemperature()) {
			desiredWS = WindowState.TILTED;
		} else {
			// outside temperature does not help in cooling the room down, let's close the window
			desiredWS = WindowState.CLOSED;
		}
		return desiredWS;
	}
}
